/* $Id: encdb.c 62 2007-05-24 06:10:38Z aldleonm $
 */

#include "encdb.h"
#include "extern.h"
#include "util.h"
#include "file.h"
#include "crypt.h"
#include "config.h"

extern struct _dbi *db_i;
extern struct _dbid *db_id;
extern int debug;

void License(void)
{
    printf("\n\tThis program is free software; you can redistribute it and/or modify\n ");
    printf("\tit under the terms of the GNU General Public License as published by\n ");
    printf("\tthe Free Software Foundation; either version 3 of the License, or\n ");
    printf("\t(at your option) any later version.\n ");
    printf("\tThis program is distributed in the hope that it will be useful,\n ");
    printf("\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n ");
    printf("\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n ");
    printf("\tGNU General Public License for more details.\n\n");
    printf("\tYou should have received a copy of the GNU General Public License\n ");
    printf("\talong with this program; if not, write to the Free Software Foundation,\n");
    printf("\tInc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n\n");
}

void
Usage(void)
{
	printf("%s: %s %s\n", PACKAGE_NAME, PACKAGE_VERSION, CHANGEDATE);
	License();
	printf
		("       desc: copy from file into database\n");
	printf("             encrypting it`s content with specified passphrase.\n\n");
	printf("       author: %s, email: %s\n", AUTHORS_NAMES, AUTHORS_EMAILS);
	printf("\n");
	printf("       options:\n");
	printf("         -f <dbfilename> -p <ask|file:pathname> -c [-g] \n");
	printf("         -f <dbfilename> -p <ask|file:pathname> -s \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -o <writeout> -n <keyname> [-g]  \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -i <readfrom> -n <keyname> [-g] \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -d -n <keyname> [-g] \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -l [-g] \n\n");

	printf("       The option -p can read files ( -p file:/pathtofile ) and named pipes\n");
	printf("       ( same as a file ) , or prompt and ask for a password ( -p ask ).\n\n");
}

int
main(int argc, char *argv[])
{

	FILE *iofile = 0;
	char readfile[BSZ];
	char writefile[BSZ];
	char *tmp_passwd = NULL; /* pass cmd */

	char ch;
	int ret;
	struct stat fst;
	u_int32_t fsize = 0;

	memset(readfile, 0, BSZ);
	memset(writefile, 0, BSZ);
	memset(db_i->keyname, 0, STRSZ);

	/* extern */
	db_i->action = -1;

	while ((ch = getopt(argc, argv, "f:o:i:p:n:cldhvgs")) != EOF)
		switch (ch) {
				case 'f':
					strncpy(db_i->fname, optarg, strlen(optarg));
					db_i->s_fname = strlen(optarg) + 1;
					break;
				case 'o':
					strncpy(readfile, optarg, BSZ);
					readfile[0] == '-' ? (db_i->action_subopt = 1) : 
									(db_i->action_subopt = 0);
					db_i->action = READ;
					break;
				case 'c':
					db_i->action = CREATE;
					break;
				case 'p':
					tmp_passwd = alloc(STRSZ);
					tmp_passwd = ed_getpass(optarg);
					if ( (db_i->passw = hash_password(tmp_passwd)) == NULL)
					{
						exit(1);	
					}
					break;
				case 'i':
					strncpy(writefile, optarg, strlen(optarg));
					writefile[0] == '-' ? (db_i->action_subopt = 1) : 
									(db_i->action_subopt = 0);
					db_i->action = WRITE;
					break;
				case 'd':
					db_i->action = DELETE;
					break;
				case 'n':
					strncpy(db_i->keyname, optarg, strlen(optarg));
					break;
				case 'h':
					Usage();
					exit(1);
					break;
				case 'v':
					printf("%s: %s %s %s %s\n", PACKAGE_NAME, PACKAGE_VERSION, 
													CHANGEDATE, AUTHORS_NAMES, AUTHORS_EMAILS);
					License();
					before_exit(NULL);
					exit(-1);
					break;
				case 'g':
					debug = 1;
					break;
				case 'l':
					db_i->action = LIST;
					break;
				case 'L':
					db_i->action = LIST;
					db_i->action_subopt = 1;
					break;
				case 's':
					db_i->action = STAT;
					break;
				default:
					Usage();
					exit(1);
		}


	if (db_i->action == -1) {
		Usage();
		exit(1);
	}

	/* set db name */
	db_i->name = "encdb";
	db_i->s_name = strlen(db_i->name);

	/* DB init. */
	if ((ret = db_create(&db_i->pdb, NULL, 0)) != 0) {
		perrx(1, "Error creating db handle. exiting...", 0);
	}

	if ((ret = OpenDB(db_i->pdb)) != 0) {
		fprintf(stderr,"Or wrong password.\n");
		perrx(1, "Error opening db. exiting...", 0);
	}

	if (db_i->action != CREATE && getID() != 0) {
		perrx(1, "Error getting database id. exiting...", 0);
	}

	if (db_i->action == CREATE) {
		before_exit(NULL);
		exit(0);
	}

	/* big switch */
	switch (db_i->action) {
					case WRITE:
							/* write into database */
							if (db_i->action_subopt == 0) {

								if ((iofile = fopen(writefile, "r")) == NULL) {
									perrx(1, "main(): unsuccessful call to fopen().", 1);
								}

								if ((fstat(fileno(iofile), &fst)) != 0) {
									perrx(1, "main(): unsuccessful call to fstat().", 1);
								}
								fsize = fst.st_size;
								void *crypted  = NULL;

								crypted = encrypt_from_file(db_i->passw,iofile);

								if ( WriteDB(db_i->pdb,db_i->keyname,crypted,fsize) )  
								{
									perrx(1, "main(): unsuccessful call to WriteDB().", 0);
								}

								fclose(iofile);
								before_exit(NULL);
								exit(0);

							}
						break;

					case READ:
							/* read from database */
							if (db_i->action == READ && db_i->action_subopt == 0) {

								if (((iofile = fopen(readfile, "w+")) == NULL)) {
									perrx(1, "main(): unsuccessful call to fopen().", 1);
								}
	
								void *cntn = NULL;
								u_int32_t size = 0;
		
								cntn = QueryDB(db_i->pdb, db_i->keyname, &size);
		
								if ( cntn == NULL ) {
									perrx(1, "main(): unsuccessful call to QueryDB().", 0);
								}
		
								decrypt_to_file(db_i->passw,cntn,size,iofile);
								before_exit(cntn);
								fclose(iofile);
								exit(0);

							}
							break;

					case DELETE:

							if ((DeleteDB(db_i->pdb, db_i->keyname)) != 0) {
									perrx(1, "main(): unsuccessful call to DeleteDB().", 0);
							}

							before_exit(NULL);
							exit(0);
							break;

					case LIST:

							if ((ListDB(db_i->pdb)) != 0) {
								perrx(1, "main(): unsuccessful call to ListDB().", 0);
							}

							before_exit(NULL);
							exit(0);
							break;

					case STAT:

							if ((StatDB(db_i->pdb)) != 0) {
								perrx(1, "main(): unsuccessful call to StatDB().", 0);
							}

							struct _dbid *tmp_dbid;
							u_int32_t size = 0;

							if ((tmp_dbid = (void *)QueryDB(db_i->pdb, ID_KEY, &size)) == NULL) {
								perrx(1, "main(): unsuccessful call to QueryDB().", 0);
							}

							fprintf(stdout, "Id of %s...\n", tmp_dbid->name);
							fprintf(stdout, "creation date: %s", ctime(&tmp_dbid->creation_date));
							fprintf(stdout, "last change date: %s\n", ctime(&tmp_dbid->last_change));

							before_exit(tmp_dbid);
							exit(0);
							break;
	}

	/* NOT REACHED */
	return 0;
}

/* vim: ts=2
 * END
 */
